﻿using System;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using SmlEngine.Timers;

namespace SmlEngine.UI.Controls.Menus2
{
    public class MenuEntry
    {
        private bool isTransitioning;

        #region Properties

        public string Text { get; private set; }

        public Action<MenuEntry> Selected { get; set; }
        public Action<MenuEntry> LeftPressed { get; set; }
        public Action<MenuEntry> RightPressed { get; set; }

        public bool IsChecked { get; private set; }

        public bool ForceFadeOut { get; set; }

        public Vector2 CurrentPosition { get; set; }
        public Color CurrentColor { get; private set; }
        public float CurrentScale { get; private set; }

        public Menu Menu { get; set; }
        
        #endregion

        #region Methods

        public MenuEntry(string text, Action<MenuEntry> selected, Menu menu)
        {
            Text = text;
            Selected = selected;

            CurrentScale = 1f;
            CurrentColor = Color.White;

            Menu = menu;
        }

        #region Events

        public void Select()
        {
            Selected(this);
        }

        public void Left()
        {
            if (LeftPressed != null)
                LeftPressed(this);
        }

        public void Right()
        {
            if (RightPressed != null)
                RightPressed(this);
        }

        #endregion

        #region Checking

        public void Check()
        {
            IsChecked = true;
            Transition(true, false);
        }

        public void Uncheck()
        {
            IsChecked = false;
            Transition(true, true);
        }

        public void InvertCheck()
        {
            if (IsChecked)
                Check();
            else 
                Uncheck();
        }

        #endregion

        #region Transitioning

        public void Transition(bool selected, bool pulse)
        {
            if (!isTransitioning)
            {
                isTransitioning = true;

                Color targetColor = selected ?
                    Menu.SelectedColor :
                    Menu.NormalColor;

                float TargetScale = selected ?
                    Menu.SelectedScale :
                    Menu.NormalScale;

                float time = selected ?
                    Menu.FadeInTime :
                    Menu.FadeOutTime;

                ForceFadeOut = !selected;

                Color currentColor = CurrentColor;
                float currentScale = CurrentScale;

                Action<Interpolator> completed;

                if (pulse)
                    completed = i =>
                    {
                        Pulse(targetColor, currentColor, Menu.PulseTime);
                        isTransitioning = false;
                    };
                else
                    completed = i => isTransitioning = false;

                Menu.Screen.ScreenManager.Timers.CreateInterpolator(0, 1, time, i =>
                {
                    CurrentColor = Color.Lerp(currentColor, targetColor, i.Value);
                    CurrentScale = MathHelper.Lerp(currentScale, TargetScale, i.Value);
                }, completed);
            }
        }

        private void Pulse(Color start, Color end, float length)
        {
            /* if (!ForceFadeOut)
            {
                Menu.Screen.ScreenManager.Timers.InterpolateColor(start, end, length, color => 
                {
                    if (ForceFadeOut)
                    {
                        ForceFadeOut = false;
                        Pulse(CurrentColor, Menu.NormalColor, Menu.FadeOutTime);
                        return;
                    }

                    CurrentColor = color;
                }, 
                i => 
                {
                    if (!ForceFadeOut)
                        Pulse(end, start, length);

                }, InterpolatorScales.Quadratic);
            } */
            FadeIn();
        }

        private void FadeIn()
        {
            if (!ForceFadeOut)
            {
                Menu.Screen.ScreenManager.Timers.InterpolateColor(Menu.NormalColor, Menu.SelectedColor, Menu.FadeInTime, color =>
                {
                    if (ForceFadeOut)
                    {
                        FadeOut();
                        return;
                    }

                    CurrentColor = color;
                }, i => FadeOut(), InterpolatorScales.Quadratic);
            }
        }

        private void FadeOut()
        {
            if (ForceFadeOut) 
                FadeOut(Menu.FadeOutTime, null);
            else 
                FadeOut(Menu.PulseTime, FadeIn);
        }

        private void FadeOut(float time, Action completed)
        {
            if (completed == null)
                completed = () => { };

            Menu.Screen.ScreenManager.Timers.InterpolateColor(Menu.SelectedColor, Menu.NormalColor, 
                time, color => CurrentColor = color, i => completed(), InterpolatorScales.Quadratic);
        }

        #endregion

        #region Sizing

        public int GetWidth(SpriteFont font)
        {
            return (int)font.MeasureString(Text).X;
        }

        public int GetHeight(SpriteFont font)
        {
            return font.LineSpacing;
        }

        #endregion

        #region Draw

        public void Draw(SpriteBatch spriteBatch, SpriteFont font, float alpha)
        {
            Vector2 half = font.MeasureString(Text) / 2;

            spriteBatch.DrawString(font, Text, CurrentPosition + half, 
                new Color(CurrentColor.R, CurrentColor.G, CurrentColor.B, alpha), 
                0, half, CurrentScale, SpriteEffects.None, 0);
        }

        #endregion

        #endregion
    }
}
